Re: Race conditions

Christopher Samuel (chris@rivers.dra.hmg.gb)
Thu, 08 Dec 1994 15:02:15 +0000

In message <199412080339.OAA10567@huon.melb.cpr.itg.telecom.com.au>, 
	Luke Mewburn <lm@melb.cpr.itg.telecom.com.au> writes:

> After checking the man pages in Solaris 2.x and NetBSD, and confirming
> it in NetBSD by checking the kernel sources, I discovered an interesting
> fact: when using open(), with flags of O_EXCL and O_CREAT, the following
> condition holds true:
> 	If O_EXCL is set and the last component of the pathname
> 	is a symbolic link, open() will fail even if the symbolic
> 	link points to a non-existant name.
> 
> So this can be used to ensure that people can't exploit the race
> condition where you symlink to a non-existant file and get it
> created for you, since open() is effectively testing this atomically
> for you.
> 
> Unfortunately, it appears that older systems (possibly including SunOS 4
> and Ultrix) don't have this check.

I've just checked this out with a noddy program and built the
following table up (appended at the end of this post along with the
program). The most suprising part of this exercise for me was that I
could only find *one* OS that failed the check and created the file
pointed to be the symlink!  Must be the pessimist in me.. :)

Notes:

1) The program was run as a normal user, not root.
2) The ls output looks like:

-rw-r--r--   1 chris    cs2           359 Dec  8 13:46 tst.c
lrwxrwxrwx   1 chris    cs2             3 Dec  8 14:49 symlink -> ./a
-rwxr-xr-x   1 chris    cs2          5492 Dec  8 14:50 tst*


Happy hunting, folks!
Chris
--
 Christopher Samuel     Phone:  +44 1684 894644       chris@rivers.dra.hmg.gb
 N-115, Defence Research Agency,  St Andrews Road, Great Malvern, England, UK
 postmaster@rivers.dra.hmg.gb                        usenet@rivers.dra.hmg.gb

----------------------------------------------------------
BAD - creates file with "open succeded (fh=3)":

HP-UX V7.05
----------------------------------------------------------
OK - fails with "open: File exists"

Ultrix 4.4
Ultrix 4.2
SunOS 4.1.3_U1
SunOS 4.1.3
SunOS 4.1.1
Solaris 2.1
Solaris 2.3
USL SVR4.2
Unixware 1.1.2
SCO 3.2 (ODT3)
Irix 5.2
HP-UX 9.05
NeXTstep 3.2
DRS/NX 6000 SVR4 Version 7  Level 2  Increment 2
Linux 1.1.64
----------------------------------------------------------
#include <stdio.h>
#include <fcntl.h>

static char message[]="testing";

int main(void)
{
	int fh,retval;

	fh=open("./symlink",O_RDWR|O_EXCL|O_CREAT,0644);
	
	if(fh < 0)
	{
		perror("open");
	}
	else
	{
		printf("open succeded (fh=%d)\n",fh);

		retval = write(fh,message,sizeof(message));

		if( retval == -1 )
		{
			perror("write");
		}
		close(fh);
	}
}
----------------------------------------------------------